import { Plugin, PluginKey } from 'prosemirror-state'
import { Decoration, DecorationSet, EditorView } from 'prosemirror-view'
import { ElMessageBox } from 'element-plus'
import { useCommentStore } from '@/stores/commentStore'

const commentStore = useCommentStore()
export const CommentPluginKey = new PluginKey('tiptap-comment')

export interface CommentData {
  id: string
  from: number
  to: number
  comment: string
  noteId?: string
  userId?: string
  anchorText?: string
  broken?: boolean
}

function createCommentDecoration(comment: CommentData) {
  if (comment.from === comment.to || comment.from < 0 || comment.to < 0) return null

  return Decoration.inline(comment.from, comment.to, {
    class: comment.broken ? 'tiptap-comment-broken' : 'tiptap-comment',
    title: comment.comment
  }, { commentData: comment })
}

export function CommentPlugin(): Plugin & { loadComments?: (comments: CommentData[]) => void } {
  let viewRef: EditorView | null = null
  let decoSet = DecorationSet.empty

  const plugin = new Plugin({
    key: CommentPluginKey,

    state: {
      init(_, { doc }) {
        return DecorationSet.create(doc, []) // 不使用 initialComments，空装饰初始化
      },

      apply(tr, old) {
        const meta = tr.getMeta(CommentPluginKey)

        if (meta?.decorationSet) {
          decoSet = meta.decorationSet
          return decoSet
        }

        if (meta?.add) {
          const added = Array.isArray(meta.add) ? meta.add : [meta.add]
          const newDecorations = added.map(createCommentDecoration).filter(Boolean) as Decoration[]
          decoSet = old.add(tr.doc, newDecorations)
          return decoSet
        }

        if (meta?.remove) {
          const ids = Array.isArray(meta.remove) ? meta.remove : [meta.remove]
          const toRemove = old.find().filter(d =>
            d.spec?.commentData && ids.includes(d.spec.commentData.id)
          )
          decoSet = old.remove(toRemove)
          return decoSet
        }

        if (meta?.update) {
          const updated = createCommentDecoration(meta.update)
          const toRemove = old.find().filter(d => d.spec?.commentData?.id === meta.update.id)
          decoSet = old.remove(toRemove).add(tr.doc, updated ? [updated] : [])
          return decoSet
        }

        return old.map(tr.mapping, tr.doc)
      }
    },

    props: {
      decorations() {
        return decoSet
      },

      handleClickOn(view, pos) {
        const decoSet = plugin.getState(view.state) as DecorationSet
        const decos = decoSet.find(pos, pos)
        const target = decos.find(d => d.spec?.commentData)

        if (!target) return false

        const data = target.spec.commentData as CommentData

        if (data.broken) {
          ElMessageBox.alert('⚠️ 此批注锚定的内容已被删除，需重新定位。', '批注失效')
        } else {
          ElMessageBox.prompt('修改批注内容', '编辑批注', {
            confirmButtonText: '保存',
            cancelButtonText: '删除',
            inputValue: data.comment,
            distinguishCancelAndClose: true,
          }).then(({ value }) => {
            const newComment = { ...data, comment: value }
            const tr = view.state.tr.setMeta(CommentPluginKey, { update: newComment })
            view.dispatch(tr)
            commentStore.updateComment(newComment)
          }).catch(action => {
            if (action === 'cancel') {
              const tr = view.state.tr.setMeta(CommentPluginKey, { remove: data.id })
              view.dispatch(tr)
              commentStore.deleteComment(data.id)
            }
          })
        }

        return true
      }
    },

    view(view) {
      viewRef = view
      return {
        update() {},
        destroy() {
          viewRef = null
        }
      }
    }
  }) as Plugin & {
    loadComments?: (comments: CommentData[]) => void
  }

  // 插件扩展方法：用于手动刷新批注装饰
  plugin.loadComments = (comments: CommentData[]) => {
    if (!viewRef) return
    const decorations = comments.map(createCommentDecoration).filter(Boolean) as Decoration[]
    const newSet = DecorationSet.create(viewRef.state.doc, decorations)
    const tr = viewRef.state.tr.setMeta(CommentPluginKey, { decorationSet: newSet })
    viewRef.dispatch(tr)
  }

  return plugin
}
